package org.jef.core.exception;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;

/**
 * 基本异常类,该类是为了方便后期扩展的
 * @description: BaseException
 * @author: Cheng Zhi
 * @create: 2021-03-11 14:13
 **/
public class BaseException extends RuntimeExceptionWithCode{

    private Object[] formatObjects = null;

    public BaseException(String messageCode) {
        super(messageCode);
    }

    public BaseException() {
        super();
    }

    public BaseException(String message, Throwable cause) {
        super(message, cause);
    }

    public BaseException(Throwable cause) {
        super(cause);
    }

    public BaseException(long messageCode, Object... objects) {
        this(String.valueOf(messageCode), (Throwable)null, objects);
    }

    public BaseException(String messageCode, Throwable cause, Object... objects) {
        super(messageCode, cause);
        if(cause!=null){
            String errorMsg = this.exceptionSummary(cause);
            this.formatObjects = ArrayUtils.add(objects, errorMsg);
        }else{
            this.formatObjects=objects;
        }
        if(this.formatObjects!=null){
            for(int i=0;i<formatObjects.length;i++){
                if(formatObjects[i]==null){
                    formatObjects[i] = "";
                }
            }
        }
    }

    public Object[] getFormatObjects() {
        if (formatObjects != null) {
            Object[] temp = new Object[formatObjects.length];
            System.arraycopy(formatObjects, 0, temp, 0, formatObjects.length);
            return temp;
        }
        return null;
    }

    private String exceptionSummary(Throwable e) {
        String msg = e.getLocalizedMessage();
        StackTraceElement[] stacks = e.getStackTrace();
        if (msg == null && e.getCause() != null) {
            msg = exceptionSummary(e.getCause());
        }

        String stack = stacks.length > 0 ? stacks[0].toString() : "";
        return concat(e.getClass().getSimpleName(), ":", msg, "\r\n", stack);
    }

    /**
     * 合并多个String,在参数为3个和以内时请直接使用String.concat。
     * 5个和超过5个String相加后，concat方法性能急剧下降，此时此方法最快
     *
     * @param args
     * @return
     */
    public String concat(String... args) {
        if (args.length == 1)
            return args[0];
        int n = 0;
        for (String s : args) {
            if (s == null)
                continue;
            n += s.length();
        }
        StringBuilder sb = new StringBuilder(n);
        for (String s : args) {
            if (s == null)
                continue;
            sb.append(s);
        }
        return sb.toString();
    }
}
